package postgres

import (
	"context"
	"gorm.io/gorm"
	"manager/errors"
	"manager/model"
	"manager/model/entity"
)

var Fault = &fault{}

type fault struct{}

// Create 创建
func (a *fault) Create(ctx context.Context, m *entity.Fault) (int64, error) {
	err := GetDB(ctx).Create(m).Error
	return m.Id, err
}

// Find 查找详情
func (a *fault) Find(ctx context.Context, in *model.FaultInfoRequest) (*entity.Fault, error) {
	e := &entity.Fault{}

	q := GetDB(ctx).Model(&entity.Fault{})

	if in.Id > 0 {
		err := q.First(&e, in.Id).Error
		return e, err
	}

	count := 0

	if in.UserId != nil {

		q = q.Where("user_id = ?", in.UserId)

		count++
	}

	if in.EbikeId != nil {

		q = q.Where("ebike_id = ?", in.EbikeId)

		count++
	}

	if in.EbikeName != nil {

		q = q.Where("ebike_name like ?", in.EbikeName)

		count++
	}

	if in.EbikeTypeId != nil {

		q = q.Where("ebike_type_id = ?", in.EbikeTypeId)

		count++
	}

	if in.EbikeTypeName != nil {

		q = q.Where("ebike_type_name like ?", in.EbikeTypeName)

		count++
	}

	if in.Phone != nil {

		q = q.Where("phone like ?", in.Phone)

		count++
	}

	if in.FaultId != nil {

		q = q.Where("fault_id = ?", in.FaultId)

		count++
	}

	if in.FaultName != nil {

		q = q.Where("fault_name like ?", in.FaultName)

		count++
	}

	if in.FaultDesc != nil {

		q = q.Where("fault_desc like ?", in.FaultDesc)

		count++
	}

	if in.FaultEnum != nil {

		q = q.Where("fault_enum = ?", in.FaultEnum)

		count++
	}

	if in.Level != nil {

		q = q.Where("level = ?", in.Level)

		count++
	}

	if in.SnCode != nil {

		q = q.Where("sn_code like ?", in.SnCode)

		count++
	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

		count++
	}

	if count == 0 {
		return e, errors.New("condition illegal")
	}

	err := q.First(&e).Error
	return e, err
}

// Update 更新
func (a *fault) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return GetDB(ctx).Model(&entity.Fault{}).Where("id = ?", id).Updates(dict).Error
}

// Delete 删除
func (a *fault) Delete(ctx context.Context, id int64) error {
	return GetDB(ctx).Delete(&entity.Fault{}, id).Error
}

func (a *fault) ClearFault(ctx context.Context, bikeId int64, faultEnums []int64) error {
	return GetDB(ctx).Model(&entity.Fault{}).Where("ebike_id = ? and fault_enum in ?", bikeId, faultEnums).Delete(&entity.Fault{}).Error
}

// List 列表查询
func (a *fault) List(ctx context.Context, in *model.FaultListRequest) (int, []*entity.Fault, error) {
	var (
		q      = GetDB(ctx).Model(&entity.Fault{})
		err    error
		total  int64
		faults []*entity.Fault
	)

	if in.UserId != nil {

		q = q.Where("user_id = ?", in.UserId)

	}

	if in.EbikeId != nil {

		q = q.Where("ebike_id = ?", in.EbikeId)

	}

	if in.EbikeName != nil {

		q = q.Where("ebike_name like ?", in.EbikeName)

	}

	if in.EbikeTypeId != nil {

		q = q.Where("ebike_type_id = ?", in.EbikeTypeId)

	}

	if in.EbikeTypeName != nil {

		q = q.Where("ebike_type_name like ?", in.EbikeTypeName)

	}

	if in.Phone != nil {

		q = q.Where("phone like ?", in.Phone)

	}

	if in.FaultId != nil {

		q = q.Where("fault_id = ?", in.FaultId)

	}

	if in.FaultName != nil {

		q = q.Where("fault_name like ?", in.FaultName)

	}

	if in.FaultDesc != nil {

		q = q.Where("fault_desc like ?", in.FaultDesc)

	}

	if in.FaultEnum != nil {

		q = q.Where("fault_enum = ?", in.FaultEnum)

	}

	if in.Level != nil {

		q = q.Where("level = ?", in.Level)

	}

	if in.SnCode != nil {

		q = q.Where("sn_code like ?", in.SnCode)

	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

	}

	if len(in.TimeZone) == 2 {
		q = q.Where("created_at between ? and ?", in.TimeZone[0], in.TimeZone[1])
	}

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}
	if err = q.Order("created_at desc").Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&faults).Error; err != nil {
		return 0, nil, err
	}
	return int(total), faults, nil
}

// ExecTransaction db事务执行
func (a *fault) ExecTransaction(ctx context.Context, callback func(ctx context.Context) error) error {
	return GetDB(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, DBCONTEXTKEY, tx)
		return callback(ctx)
	})
}
